
#include<vector>

//#include <unistd.h>
#include <errno.h>
#include <sys/iomsg.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "komunikacja1.2.h"

using namespace std;

Connector* Connector::instance = NULL;


Connector * Connector::getInstance()
{
	if ( !instance ) {
		instance = new Connector();
	}
	return instance;
}

Connector::Connector()
{
	connName = new char[CONN_NAME_LENGTH];
	connName[0] = 'a';
	for( int i = 0; i < CONN_NAME_LENGTH; i++)
		connName[i] = '\0';
	strcpy(connName, "NO_NAME");
	
	sem_init( & semAirportsDB, 0, 1);
}

void Connector::createListener( char * _connLocalName)
{
	
	/** zapisuje nazwe naszego kanalu**/

	strcpy(connName, _connLocalName);

	/** watek, ktory bedzie nasluchiwal**/	
	pthread_attr_t attr;

   	pthread_attr_init( &attr );
   	pthread_attr_setdetachstate(
      		&attr, PTHREAD_CREATE_DETACHED );
      		
	pthread_create( NULL, &attr, &run , _connLocalName );
}


/**
	Funkcja zajmujaca sie komunikatem, ktory przyszedl przez siec
**/
void * messageReceived( void * arg)
{

	Message * msg = (Message *)arg;
	
	sem_wait(&Connector::getInstance()->semAirportsDB);
	cout <<endl << "sender   : " << msg->getConnSenderName()
		   << endl << "receiver : " << msg->getConnReceiverName()
		   << endl << "type     : " << msg->verboseType(msg->getType()) << " (" <<msg->getType()<<" )" <<endl;
	
		   
    switch( msg->getType()) {
		case GET_AIRPORTS_EV_DB :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		case RES_GET_AIRPORTS_EV_DB :	
			
		
			cout << "Nr " << msg->getNr() << " of " << msg->getMessageLength()
				   <<  ", id_lot : " << msg->getIntArg1()<< ", poj : " << msg->getIntArg2()
				   << ", pas_szer : " <<msg->getIntArg3() << ", pas_dl : " <<msg->getIntArg4()
				   << ", aktyw : "<<msg->getBoolArg1() << endl<<", szer_geo : " << msg->getFloatArg1()
				   << ", dl_geo : " <<msg->getFloatArg2() <<", nazwa : " <<msg->getStringArg1() <<endl; 
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case GET_PLANES_EV_DB :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		case RES_GET_PLANES_EV_DB :	
			
			cout << "Nr " << msg->getNr() << " of " << msg->getMessageLength()
				   <<  ", czas_obsl : " << msg->getIntArg1()<< ", bak : " << msg->getFloatArg1()
				   << ", spal : " <<msg->getFloatArg2() << ", predk : " <<msg->getFloatArg3()
				   << ", pas_szer : "<<msg->getBoolArg1() << endl <<", nazwa : " <<msg->getStringArg1() <<endl; 
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
				
		case GET_EVENTS_EV_DB :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case RES_GET_EVENTS_EV_DB :	
		
			cout << "Nr " << msg->getNr() << " of " << msg->getMessageLength()
				   <<  ", typ : " << msg->getIntArg1()<< ", podtyp : " << msg->getIntArg2()
				   << ", nazwa : " <<msg->getStringArg1()<<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;

		case GET_AIRPORT_AI_DB :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case RES_GET_AIRPORT_AI_DB :	
		
			cout<<  ", nazwa : " << msg->getStringArg1()<< ", id_lot : " << msg->getIntArg4()
				   << ", poj : " <<msg->getIntArg1() << ", szer_geo : " <<msg->getFloatArg1()
				   << ", dl_geo : "<<msg->getFloatArg2() << endl<<", pas_szer : " << msg->getIntArg2()
				   << ", pas_wa : " <<msg->getIntArg3() <<endl; 
			sem_post(&Connector::getInstance()->semAirportsDB);		
			break;
			
		case GET_PLANE_AI_DB :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		case RES_GET_PLANE_AI_DB :	
		
			cout <<  ", czas_obs : " << msg->getIntArg1()<< ", czy_szer : " << msg->getBoolArg1() << endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_PODAJ_LICZBE_LOTNISK :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_LAP_LICZBE_LOTNISK :	
		
			cout <<  ", liczba_lotnisk : " << msg->getIntArg1()<< endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;

		case MSG_PRZESLIJ_LOTNISKA :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_LAP_WSPOLRZEDNE_LOTNISKA :	
			
			cout<< "Nr " << msg->getNr() << " of " << msg->getMessageLength()
				   <<  ", id_lot : " << msg->getIntArg1()<< ", szer_geo : " << msg->getFloatArg1()
				   << ", dlu_geo : " <<msg->getFloatArg2()<<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_ZAPODAJ_DANE_TECHNICZNE :	
		
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		case MSG_RES_ZAPODAJ_DANE_TECHNICZNE :	
			
			cout<<  ", bak : " << msg->getFloatArg1()<< ", spalanie : " << msg->getFloatArg2()
				   << ", predk : " <<msg->getFloatArg3()<<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		
		case FAILURE_EV_PL :
			
			cout<<  ", nazw_aw : " << msg->getStringArg1()<< ", podtyp : " << msg->getStringArg2()
				   << ", stopien : " <<msg->getIntArg1()<<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		
		case FAILURE_OVER_EV_PL :
			
			cout<<  ", nazw_aw : " << msg->getStringArg1() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_ZMIEN_KURS :
			
			cout<<  ", pos.1 : " << msg->getFloatArg1()<< ", pos.2 : " << msg->getFloatArg2()
				   << ", nazwaLot : " <<msg->getStringArg1()<<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
	
		case  ACTIVATE_AIRPORT :
			
			cout<<  ", id_lot : " << msg->getIntArg1() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case  DISACTIVATE_AIRPORT :
			
			cout<<  ", id_lot : " << msg->getIntArg1() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
	
		case FAILURE_EV_PO :
			
			cout<<  ", nazwa : " << msg->getStringArg1()<< ", podtyp : " << msg->getStringArg2()
				   << ", stopien : " <<msg->getIntArg1()<<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;

		case FAILURE_OVER_EV_PO :
		
			cout<<  ", nazw_aw : " << msg->getStringArg1() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	
			
		case MSG_ZGLOSZENIE_GOTOWOSCI_DO_STARTU :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	
			
		case  MSG_ZGLOSZENIE_GOTOWOSCI_DO_LADOWANIA :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	
			
		case MSG_ZEZWOLENIE_NA_START :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	
			
		case  MSG_MOZESZ_LADOWAC :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	
			
		case MSG_AKTUALNA_POZYCJA :
			
			cout<<  ", pos.1 : " << msg->getFloatArg1()<< ", pos.2 : " << msg->getFloatArg2() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_NOWA_MASZYNA_W_STREFIE :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	

		case  MSG_OPUSCILES_STREFE_WPLYWOW :
			
			sem_post(&Connector::getInstance()->semAirportsDB);			
			break;	
			
		case MSG_GON_SIE :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;	
			
		case MSG_KONCZE_SMIGAC :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			cout<<  " lotnisko : " << msg->getStringArg1()<<endl;
			break;	
				
		case ZAKAZ_LADOWANIA :
			
			cout<<  ", czas : " << msg->getIntArg1() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case ZAKAZ_STARTU :
			
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
			
		case MSG_POJAWIAM_SIE_NA_LOTNISKU :
			
			cout<<  ", typ : " << msg->getStringArg1() <<endl;
			sem_post(&Connector::getInstance()->semAirportsDB);
			break;
		/**
 
		**/
			
			
	 	default :
	 
	 		cout << "ERROR ERROR ERROR. Nieznany typ komunikatu" <<endl <<endl;
	 		sem_post(&Connector::getInstance()->semAirportsDB);
	 		break;
	}
		 
}


void messageHandler( Message  * msg)
{
	//cout << "messageHandler" <<endl;

	/* watek, ktory bedzie nasluchiwal*/
	pthread_attr_t attr;

   	pthread_attr_init( &attr );
   	pthread_attr_setdetachstate(
      		&attr, PTHREAD_CREATE_DETACHED );
      		
	pthread_create( NULL, &attr, &messageReceived, msg );
}


/**
	Funkcja obslugujaca nasluchiwanie na zadania z sieci
**/
void* run( void * arg) {

   name_attach_t *attach;
   
   Message msg;
   Message * msgProper;
   int rcvid;

	
	cout << "Nazwa nasluchiwacza #"<< (char *)arg << endl;
	
   /* Create a local name (/dev/name/local/...) */
   if ((attach = name_attach(NULL, (char * ) arg, NAME_FLAG_ATTACH_GLOBAL)) == NULL) {
   	cout << "ERROR,  run: #"<< strerror(errno) << endl;
       return (void*)EXIT_FAILURE;
   }

   /* Do your MsgReceive's here now with the chid */
   while (1) {
  
	 rcvid = MsgReceive(attach->chid, &(msg.data), sizeof(msg.data), NULL);

       if (rcvid == -1) {/* Error condition, exit */
           break;
       }

       if (rcvid == 0) {/* Pulse received */
           switch (msg.data.hdr.code) {
           case _PULSE_CODE_DISCONNECT:
               /*
                * A client disconnected all its connections (called
                * name_close() for each name_open() of our name) or
                * terminated
                */
               ConnectDetach(msg.data.hdr.scoid);
               break;
           case _PULSE_CODE_UNBLOCK:
               /*
                * REPLY blocked client wants to unblock (was hit by
                * a signal or timed out).  It's up to you if you
                * reply now or later.
                */
               break;
           
           }
           continue;
       }


       /* name_open() sends a connect message, must EOK this */
       if (msg.data.hdr.type == _IO_CONNECT ) {
           MsgReply( rcvid, EOK, NULL, 0 );
           continue;
       }

       /* Some other QNX IO message was received; reject it */
       if (msg.data.hdr.type > _IO_BASE && msg.data.hdr.type <= _IO_MAX ) {
           MsgError( rcvid, ENOSYS );
           continue;
       }

       /* A message (presumable ours) received, handle */
    	MsgReply(rcvid, EOK, 0, 0);

		msgProper = new Message();
		msg.copyMessage(msgProper);    
    
       messageHandler(msgProper);
   }

   /* Remove the name from the space */
   name_detach(attach, 0);

   return (void*)EXIT_SUCCESS;
}


